/**
 * Copyright 2019 吉鼎科技.

 * <p>
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * <p>
 * http://www.apache.org/licenses/LICENSE-2.0
 * <p>
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package cn.easyplatform.web;

import cn.easyplatform.lang.Files;
import cn.easyplatform.messages.request.SimpleRequestMessage;
import cn.easyplatform.messages.vos.EnvVo;
import cn.easyplatform.messages.vos.LoginVo;
import cn.easyplatform.spi.service.ApplicationService;
import cn.easyplatform.spi.service.TaskService;
import cn.easyplatform.type.Constants;
import cn.easyplatform.type.IResponseMessage;
import cn.easyplatform.type.UserType;
import cn.easyplatform.web.contexts.Contexts;
import cn.easyplatform.web.service.ServiceLocator;
import org.apache.commons.io.IOUtils;
import org.apache.commons.io.input.BOMInputStream;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.core.Appender;
import org.apache.logging.log4j.core.LoggerContext;
import org.apache.logging.log4j.core.appender.RollingRandomAccessFileAppender;
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Node;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.zkoss.zk.ui.Desktop;
import org.zkoss.zk.ui.Executions;
import org.zkoss.zk.ui.Session;
import org.zkoss.zk.ui.WebApp;

import java.io.*;
import java.util.Iterator;
import java.util.List;


/**
 * @author <a href="mailto:davidchen@epclouds.com">littleDog</a> <br/>
 * @since 2.0.0 <br/>
 */
public abstract class Lifecycle {

    private static Logger log;

    /**
     * @param app
     * @throws Exception
     */
    public static void beginApp(WebApp app) throws Exception {
        LoggerContext ctx = (LoggerContext) LogManager.getContext(false);
        String logPath = null;
        if (System.getProperty("log4j.configurationFile") == null || System.getProperty("log4j2.configurationFile") == null) {
            String log4jConfigFile = app.getRealPath("WEB-INF/config/log4j2.xml");
            InputStream input = null;
            Document doc = DocumentHelper.parseText(IOUtils.toString(input = new BOMInputStream(new FileInputStream(log4jConfigFile))));
            input.close();
            Node node = doc.selectSingleNode("//Property[@name='log-path']");
            File file = new File(app.getRealPath(""));
            node.setText(logPath = file.getParentFile().getParentFile().getCanonicalPath() + File.separatorChar + "logs");
            Writer writer = null;
            doc.write(writer = new FileWriter(log4jConfigFile));
            writer.close();
            System.setProperty("log4j.configurationFile", log4jConfigFile);
            ctx.reconfigure();
        } else {
            Iterator<Appender> itr = ctx.getConfiguration().getAppenders().values().iterator();
            while (itr.hasNext()) {
                Appender appender = itr.next();
                if (appender instanceof RollingRandomAccessFileAppender) {
                    RollingRandomAccessFileAppender rraf = (RollingRandomAccessFileAppender) appender;
                    File file = new File(rraf.getFileName());
                    logPath = file.getCanonicalFile().getParent();
                    break;
                }
            }
        }
        log = LoggerFactory.getLogger(Lifecycle.class);
        if (log.isInfoEnabled())
            log.info("The Log output directory is {}", logPath);
        app.setAttribute("easyplatform.log", logPath);
        WebApps.me().start(app);
    }


    /**
     * 结束应用系统
     */
    public static void endApp(WebApp app) {
        WebApps.me().stop();
    }

    /**
     * 开始会话
     *
     * @param session
     */
    public static void beginSession(Session session) {
    }

    /**
     * 结束会话
     *
     * @param session
     */
    public static void endSession(Session session) {
    }

    /**
     * @param desktop
     */
    public static void beginDesktop(Desktop desktop) {
        if (log.isDebugEnabled())
            log.debug("begin desktop {}", desktop);
    }

    /**
     * @param desktop
     */
    public static void endDesktop(Desktop desktop) {
        Session sess = desktop.getSession();
        LoginVo user = (LoginVo) sess.getAttribute(Contexts.PLATFORM_USER);
        if (user != null) {
            List<String> ids = (List<String>) desktop.removeAttribute(Contexts.ANONYMOUS_TASKS);
            List<String> sessIds = (List<String>) desktop.getSession().getAttribute(Contexts.ANONYMOUS_TASKS);
            if (ids != null) {//在外面打开的功能
                TaskService tcs = ServiceLocator.lookup(
                        TaskService.class);
                for (String id : ids) {
                    tcs.close(new SimpleRequestMessage(id, null));
                    sessIds.remove(id);
                }
            } else if (user.getType() != UserType.TYPE_SUPER) {//主页面
                ApplicationService tc = ServiceLocator
                        .lookup(ApplicationService.class);
                SimpleRequestMessage req;
                if (sessIds == null || sessIds.isEmpty())
                    req = new SimpleRequestMessage();
                else req = new SimpleRequestMessage(sessIds.toArray());//外面打开的功能不清除
                IResponseMessage<?> resp = tc.purge(req);
                if (!resp.isSuccess()) {
                    EnvVo env = (EnvVo) sess.getAttribute(Contexts.PLATFORM_APP_ENV);
                    if (env != null && env.getLogoutUrl() != null)
                        Executions.sendRedirect(env.getLogoutUrl());
                    sess.removeAttribute(Constants.SESSION_ID);
                    sess.removeAttribute(Contexts.PLATFORM_APP_ENV);
                    sess.removeAttribute(Contexts.PLATFORM_USER);
                    sess.removeAttribute(Contexts.PLATFORM_USER_ORGS);
                }
            }
        }
        if (log.isDebugEnabled())
            log.debug("end desktop {}", desktop);
    }
}
